package com.wangsh.train.common.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.Binarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

/**
 * 二维码工具类
 * 
 * @author Administrator
 */
@Component
public class QRcodeUtil
{
	/**
	 * 根据一个字符串生成一个二维码
	 * 
	 * @param content 二维码中的内容
	 * @param os      二维码输出的流
	 */
	public void contentToQrcode(String content, OutputStream os) throws Exception
	{
		try
		{
			// 设置图像宽度
			int width = 200;
			// 设置图像高度
			int height = 200;
			// 设置图像类型
			String format = "png";
			Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
			// 设置编码格式
			hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
			// 设置二维码级别
			hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
			hints.put(EncodeHintType.MARGIN, 0);
			// 1、读取文件转换为字节数组
			BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
			// ByteArrayOutputStream out = new ByteArrayOutputStream();
			// BufferedImage image = new BufferedImage(width,
			// height,BufferedImage.TYPE_INT_RGB);
			// toBufferedImage：image流数据处理
			BufferedImage image = toBufferedImage(bitMatrix);
			ImageIO.write(image, format, os);
		} catch (Exception e)
		{
			ConstatFinalUtil.SYS_LOGGER.error("内容变成二维码失败了;",e);
		}
	}
	
	/**
	 * 根据一个字符串生成一个二维码
	 * 
	 * @param content 二维码中的内容
	 * @param os      二维码输出的流
	 */
	public void contentToQrcode(String content, OutputStream os,InputStream inputStream) throws Exception
	{
		try
		{
			// 设置图像宽度
			int width = 200;
			// 设置图像高度
			int height = 200;
			// 设置图像类型
			String format = "png";
			Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
			// 设置编码格式
			hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
			// 设置二维码级别
			hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
			hints.put(EncodeHintType.MARGIN, 0);
			// 1、读取文件转换为字节数组
			BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
			// ByteArrayOutputStream out = new ByteArrayOutputStream();
			// BufferedImage image = new BufferedImage(width,
			// height,BufferedImage.TYPE_INT_RGB);
			// toBufferedImage：image流数据处理
			BufferedImage image = toBufferedImage(bitMatrix);
			if(inputStream != null)
			{
				/* 设置logo */
				image = inserLogo(image, inputStream);
			}
			ImageIO.write(image, format, os);
		} catch (Exception e)
		{
			ConstatFinalUtil.SYS_LOGGER.error("内容变成二维码失败了;",e);
		}
	}
	
	/**
	 * 设置 logo
	 * 
	 * @param matrixImage 源二维码图片
	 * @return 返回带有logo的二维码图片
	 * @throws IOException
	 * @author Administrator sangwenhao
	 */
	private BufferedImage inserLogo(BufferedImage matrixImage,InputStream inputStream) throws IOException
	{
		/**
		 * 读取二维码图片，并构建绘图对象
		 */
		Graphics2D g2 = matrixImage.createGraphics();

		int matrixWidth = matrixImage.getWidth();
		int matrixHeigh = matrixImage.getHeight();

		/**
		 * 读取Logo图片
		 */
		BufferedImage logo = ImageIO.read(inputStream);

		// 开始绘制图片
		g2.drawImage(logo, matrixWidth / 5 * 2, matrixHeigh / 5 * 2, matrixWidth / 5, matrixHeigh / 5, null);// 绘制
		BasicStroke stroke = new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
		g2.setStroke(stroke);// 设置笔画对象
		// 指定弧度的圆角矩形
		RoundRectangle2D.Float round = new RoundRectangle2D.Float(matrixWidth / 5 * 2, matrixHeigh / 5 * 2,
				matrixWidth / 5, matrixHeigh / 5, 20, 20);
		g2.setColor(Color.white);
		g2.draw(round);// 绘制圆弧矩形

		// 设置logo 有一道灰色边框
		BasicStroke stroke2 = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
		g2.setStroke(stroke2);// 设置笔画对象
		RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(matrixWidth / 5 * 2 + 2, matrixHeigh / 5 * 2 + 2,
				matrixWidth / 5 - 4, matrixHeigh / 5 - 4, 20, 20);
		g2.setColor(new Color(128, 128, 128));
		g2.draw(round2);// 绘制圆弧矩形

		g2.dispose();
		matrixImage.flush();
		return matrixImage;
	}

	/**
	 * image流数据处理
	 *
	 * @author ianly
	 */
	public BufferedImage toBufferedImage(BitMatrix matrix)
	{
		int width = matrix.getWidth();
		int height = matrix.getHeight();
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		for (int x = 0; x < width; x++)
		{
			for (int y = 0; y < height; y++)
			{
				image.setRGB(x, y, matrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
			}
		}
		return image;
	}

	/**
	 * 解析二维码方法
	 * 
	 * @param is 输入流为一张二维码图片,必须是png格式
	 * @return 二维码中的内容
	 */
	public String qrcodeToContent(InputStream is)
	{
		String content = null;
		BufferedImage image;
		try
		{
			/* 读取输入流 */
			image = ImageIO.read(is);
			LuminanceSource source = new BufferedImageLuminanceSource(image);
			Binarizer binarizer = new HybridBinarizer(source);
			BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
			Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
			hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
			Result result = new MultiFormatReader().decode(binaryBitmap, hints);// 对图像进行解码
			content = result.getText();
		} catch (Exception e)
		{
			ConstatFinalUtil.SYS_LOGGER.error("解析二维码失败了;",e);
		}
		return content;
	}

	public static void main(String[] args)
	{
		QRcodeUtil rcodeUtil = new QRcodeUtil();
		try
		{
			String content = "http://www.baidu.com" ;
			File file = new File("d:/1.png");
			/* 生成二维码 */
			FileOutputStream fos = new FileOutputStream(file);
			rcodeUtil.contentToQrcode(content, fos);
			
			file = new File("d:/2.png");
			File logoFile = new File("d:/logo.png");
			FileInputStream logoFis = new FileInputStream(logoFile);
			/* 生成二维码 */
			fos = new FileOutputStream(file);
			rcodeUtil.contentToQrcode(content, fos,logoFis);
			
			/* 解析二维码 */
			FileInputStream fis = new FileInputStream(file);
			String resContent = rcodeUtil.qrcodeToContent(fis);
			System.out.println("==二维码中的内容==" + resContent);
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}
}
